package net.yambal.RTM.RestWrapper
{
	import mx.rpc.events.FaultEvent;
	import mx.utils.ObjectUtil;
	
	import net.yambal.RTM.Event.RestErrorEvent;
	import net.yambal.RTM.Event.RestEvent;
	import net.yambal.RTM.Event.TimelineEvent;
	import net.yambal.RTM.Items.RTMTransaction;
	import net.yambal.RTM.Utilty.RTMBooleanUtil;
	import net.yambal.RTM.Utilty.RTMTimelineGetter;

	public class RestManager
	{
		public function RestManager()
		{
		}
		
		/**
		 * メソッドを実行する
		 **/
		public function doMethod(
			method_name:String
			, parameta:Object
			, call_back:Function
			, error_call_back:Function
			, is_need_timeline:Boolean
			, shared_secret:String = null
			, transaction_name:String = null):void{
				
			var ro:Object = new Object();
			ro.method_name = method_name;
			ro.call_back = call_back;
			ro.error_call_back = error_call_back;
			ro.parameta = parameta;
			ro.shared_secret = shared_secret;
			ro.transaction_name = transaction_name;
			
			if(is_need_timeline){
				// TimeLineが必要なメソッド
				if(parameta && parameta.api_key && shared_secret && parameta.auth_token){
					var tlg:RTMTimelineGetter = new RTMTimelineGetter();
					tlg.getTimeline(parameta.api_key, shared_secret, parameta.auth_token, this.onGetTL, ro);
				
				}else{
					// パラメタ不足
				}
				return;
			}

			this.request(ro);
		}
		
		// タイムラインを取得する
		private function onGetTL(e:TimelineEvent, ro:Object):void{
			ro.parameta.timeline = e.timeline;
			this.request(ro);
		}
		
		// メソッドを実行する
		private function request(ro:Object):void{
			var method_name:String = ro.method_name;
			var call_back:Function = ro.call_back;
			var shared_secret:String = ro.shared_secret;
			
			var s:RestService= new RestService(ro.method_name, shared_secret, ro);

			// オブジェクトからパラメタを生成し、リクエストに詰める
			var pa:Array = this.toArray(ro.parameta);
			for(var num:int = 0; num < pa.length; num ++){
				var p_name:String = Object(pa[num]).name;
				var aug:String = Object(pa[num]).aug;
				s.addParameta(p_name, aug);
			}
			
			s.addEventListener(FaultEvent.FAULT, this.onFault);
			s.addEventListener(RestErrorEvent.RTM_FAULT, this.onRTMFaultRes);
			s.addEventListener(RestEvent.RTM_RESULT, this.onRes);
			
			s.send();
		}
		
		// HTTPサービスのＦａｕｌｔ
		private function onFault(e:FaultEvent):void{
			var s:RestService = e.currentTarget as RestService;
			s.removeEventListener(FaultEvent.FAULT, this.onFault);
			s.removeEventListener(RestErrorEvent.RTM_FAULT, this.onRTMFaultRes);
			s.removeEventListener(RestEvent.RTM_RESULT, this.onRes);
			
			s.relay_obj.error_call_back(e.fault.errorID, e.fault.faultString, s.relay_obj);
		}
		
		// 失敗
		private function onRTMFaultRes(e:RestErrorEvent):void{
			var s:RestService = e.currentTarget as RestService;
			s.removeEventListener(FaultEvent.FAULT, this.onFault);
			s.removeEventListener(RestErrorEvent.RTM_FAULT, this.onRTMFaultRes);
			s.removeEventListener(RestEvent.RTM_RESULT, this.onRes);
			
			e.relay_obj.error_call_back(e.code, e.massage, e.relay_obj);
		}
		
		//成功
		private function onRes(e:RestEvent):void{
			trace("onRes@" + this);
			var s:RestService = e.currentTarget as RestService;
			s.removeEventListener(FaultEvent.FAULT, this.onFault);
			s.removeEventListener(RestErrorEvent.RTM_FAULT, this.onRTMFaultRes);
			s.removeEventListener(RestEvent.RTM_RESULT, this.onRes);
			
			var t:RTMTransaction = new RTMTransaction();
			var tx:XMLList = e.result_xml.descendants("transaction");
			if(tx){
				t.id = tx.@id;
				t.undoable = RTMBooleanUtil.toBoolean(tx.@undoable);
				t.process = e.relay_obj.transaction_name;
			}
			
			e.relay_obj.call_back(e.result_xml, e.relay_obj, t);
		}
		
		//----------------------------------------------------------------------------
		/**
		 * Objectに詰めたパラメタをArray(.name .aug)に詰めて返す
		 **/
		public function toArray(obj:Object):Array{
			var ps:String = ObjectUtil.toString(obj);
			var psa:Array = ps.split("\n  ");
			var ret:Array = new Array();
			var reg:RegExp = new RegExp("\"","gi");
			
			for(var num:int = 0; num < psa.length; num ++){
				var name_aug:Array = String(psa[num]).split(" = ");
				var o:Object = new Object();
				o.name = name_aug[0];
				
				var aug:String = name_aug[1];
				if(aug){
					aug = aug.replace(reg,"");
				}
				
				o.aug = String(aug);
				ret.push(o);
				
				
			}
			
			ret.shift();
			
			return ret;
		}
	}
}